#include <stdio.h>

/*
 * 从汇编层面看，C++类(class)的组织方式和结构体数据完全一致。
 */

class c
{
	private:
	int v1;
	int v2;
	public:
	c() {
		v1 = 667;
		v2 = 999;
	}

	c(int a, int b)
	{
		v1 = a;
		v2 = b;
	}

	void dump() {
		printf("%d, %d\n", v1, v2);
	}
};

int main()
{
	class c c1;
	class c c2(5, 6);

	c1.dump();
	c2.dump();

	return 0;
}

#if 0

为什么这些函数有这些奇怪的名字？
其实这是编译器对函数名称进行改编（name mangling）的结果。

名称改编是一种在编译过程中，用ASCII字符串将函数、变量的名称重新改编的机制。
改编后的方法（类成员函数）名称就被用作该程序内部的函数名。这完全是因为编译器
Linker和加载DLL的OS装载器均不能识别C++或OOP（面向对象的变成语言）的数据结构。


构造函数本身就是一种函数，它们使用ECX存储结构体的指针，然后将指针复制到其自己
的局部变量里。当然，第二步不是必须的。

从C++的标准可知，构造函数的返回值是一个新建立的对象的指针，即this指针。

/*
 * intel
 */
0000000000001169 <main>:
    1169:	f3 0f 1e fa          	endbr64 
    116d:	55                   	push   %rbp				// rsp=rsp-8, rsp=rbp ===> subq $8,%rsp, movq %rbp,(%rsp)
    116e:	48 89 e5             	mov    %rsp,%rbp		// rbp=rsp
    1171:	48 83 ec 20          	sub    $0x20,%rsp		// rsp = rsp-0x20
    1175:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax	// 把fs的偏移值x28放入rax
															// 指向特定于线程或定义的结构
															// %fs:0x28主要是用来起sentinel(哨兵)的作用，
    117c:	00 00 
    117e:	48 89 45 f8          	mov    %rax,-0x8(%rbp)	// 防止overflow的，即使用了8字节进行安全保护
    1182:	31 c0                	xor    %eax,%eax		// eax 清零
    1184:	48 8d 45 e8          	lea    -0x18(%rbp),%rax	// rax = rbp-0x18 = c1 = this
    1188:	48 89 c7             	mov    %rax,%rdi		// rdi = rax
    118b:	e8 4a 00 00 00       	callq  11da <_ZN1cC1Ev>	// _ZN1cC1Ev(rdi)
    1190:	48 8d 45 f0          	lea    -0x10(%rbp),%rax	// rax = rpb-0x10 = c2 = this
    1194:	ba 06 00 00 00       	mov    $0x6,%edx		// edx = 6
    1199:	be 05 00 00 00       	mov    $0x5,%esi		// esi = 5
    119e:	48 89 c7             	mov    %rax,%rdi		// rdi = rax
    11a1:	e8 58 00 00 00       	callq  11fe <_ZN1cC1Eii>	// _ZN1cC1Eii(rdi, esi, edx)
    11a6:	48 8d 45 e8          	lea    -0x18(%rbp),%rax	// rax = c1 = this
    11aa:	48 89 c7             	mov    %rax,%rdi		// rdi = rax
    11ad:	e8 74 00 00 00       	callq  1226 <_ZN1c4dumpEv>	// _ZN1c4dumpEv(rdi)
    11b2:	48 8d 45 f0          	lea    -0x10(%rbp),%rax		// rax = c2 = this
    11b6:	48 89 c7             	mov    %rax,%rdi			// rdi = rax
    11b9:	e8 68 00 00 00       	callq  1226 <_ZN1c4dumpEv>	// _ZN1c4dumpEv(rdi)
    11be:	b8 00 00 00 00       	mov    $0x0,%eax			// eax = 0
    11c3:	48 8b 4d f8          	mov    -0x8(%rbp),%rcx	// 防止overflow
    11c7:	64 48 33 0c 25 28 00 	xor    %fs:0x28,%rcx	// fs:0x28 = 0
    11ce:	00 00 
    11d0:	74 05                	je     11d7 <main+0x6e>	// 上面xor指令结果为零，执行正常退出，否则溢出检测失败报错
    11d2:	e8 89 fe ff ff       	callq  1060 <__stack_chk_fail@plt>	// 溢出检测
    11d7:	c9                   	leaveq					// ===> mov %rbp,%rsp, pop %rbp
    11d8:	c3                   	retq					// ===> pop %rip
    11d9:	90                   	nop

00000000000011da <_ZN1cC1Ev>:
    11da:	f3 0f 1e fa          	endbr64 
    11de:	55                   	push   %rbp				// rsp=rsp-8, rsp=rbp ===> subq $8,%rsp, movq %rbp,(%rsp)
    11df:	48 89 e5             	mov    %rsp,%rbp		// rbp=rsp
    11e2:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)	// rbp-0x8 = rdi
    11e6:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = rbp-0x8 = rdi
    11ea:	c7 00 9b 02 00 00    	movl   $0x29b,(%rax)	// rax = 0x29b = 667
    11f0:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = rbp-0x8 = rdi
    11f4:	c7 40 04 e7 03 00 00 	movl   $0x3e7,0x4(%rax)	// rax+4 = 0x3e7 = 999
    11fb:	90                   	nop
    11fc:	5d                   	pop    %rbp				// rbp=rsp, rsp+8 ===> movq %rsp,(%rbp), addq $8, (%rsp)
    11fd:	c3                   	retq					// ===> pop %rip

00000000000011fe <_ZN1cC1Eii>:
    11fe:	f3 0f 1e fa          	endbr64 
    1202:	55                   	push   %rbp				// rsp=rsp-8, rsp=rbp ===> subq $8,%rsp, movq %rbp,(%rsp)
    1203:	48 89 e5             	mov    %rsp,%rbp		// rbp=rsp
    1206:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)	// rbp-0x8 = rdi = this
    120a:	89 75 f4             	mov    %esi,-0xc(%rbp)	// rbp-0xc = esi = 5
    120d:	89 55 f0             	mov    %edx,-0x10(%rbp)	// rpb-0x10 = edx = 6
    1210:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = this
    1214:	8b 55 f4             	mov    -0xc(%rbp),%edx	// edx = 5
    1217:	89 10                	mov    %edx,(%rax)		// rax = 5		===> this.v1 = 5
    1219:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = this
    121d:	8b 55 f0             	mov    -0x10(%rbp),%edx	// edx = 6
    1220:	89 50 04             	mov    %edx,0x4(%rax)	// rax+0x4 = 6	===> this.v2 = 6
    1223:	90                   	nop
    1224:	5d                   	pop    %rbp				// rbp=rsp, rsp+8 ===> movq %rsp,(%rbp), addq $8, (%rsp)
    1225:	c3                   	retq					// ===> pop %rip

0000000000001226 <_ZN1c4dumpEv>:
    1226:	f3 0f 1e fa          	endbr64 
    122a:	55                   	push   %rbp				// rsp=rsp-8, rsp=rbp ===> subq $8,%rsp, movq %rbp,(%rsp)
    122b:	48 89 e5             	mov    %rsp,%rbp		// rbp=rsp
    122e:	48 83 ec 10          	sub    $0x10,%rsp		// rsp = rsp-0x10
    1232:	48 89 7d f8          	mov    %rdi,-0x8(%rbp)	// rbp-0x8 = rdi = this
    1236:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = this.v1
    123a:	8b 50 04             	mov    0x4(%rax),%edx	// edx = rax+0x4 = this.v2
    123d:	48 8b 45 f8          	mov    -0x8(%rbp),%rax	// rax = this.v1
    1241:	8b 00                	mov    (%rax),%eax		// eax = this.v1
    1243:	89 c6                	mov    %eax,%esi		// esi = this.v1
    1245:	48 8d 3d b8 0d 00 00 	lea    0xdb8(%rip),%rdi        # 2004 <_IO_stdin_used+0x4> // rdi = "%d, %d\n"
    124c:	b8 00 00 00 00       	mov    $0x0,%eax			// eax = 0
    1251:	e8 1a fe ff ff       	callq  1070 <printf@plt>	// printf(rdi, esi, edx)
    1256:	90                   	nop
    1257:	c9                   	leaveq					// ===> mov %rbp,%rsp, pop %rbp
    1258:	c3                   	retq					// ===> pop %rip
    1259:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

/*
 * arm
 */
int main()
{
   104b0:	b580      	push	{r7, lr}
   104b2:	b084      	sub	sp, #16				/* sp = sp - 16 */
   104b4:	af00      	add	r7, sp, #0			/* r7 = sp + 0 */
	class c c1;
   104b6:	f107 0308 	add.w	r3, r7, #8		/* r3 = sp + 8, 存储对象c1的this指针 */
   104ba:	4618      	mov	r0, r3				/* parameter 1 */
   104bc:	f000 f814 	bl	104e8 <_ZN1cC1Ev>	/* 调用构造函数 */
	class c c2(5, 6);
   104c0:	463b      	mov	r3, r7				/* r3 = sp 存储对象c2的this指针 */
   104c2:	2206      	movs	r2, #6			/* parameter 3 */
   104c4:	2105      	movs	r1, #5			/* parameter 2 */
   104c6:	4618      	mov	r0, r3				/* parameter 1 */
   104c8:	f000 f821 	bl	1050e <_ZN1cC1Eii>	/* 调用构造函数 */

	c1.dump();
   104cc:	f107 0308 	add.w	r3, r7, #8		/* r3 = sp + 8 存储对象c1的this指针 */		
   104d0:	4618      	mov	r0, r3				/* r0 = this */
   104d2:	f000 f82f 	bl	10534 <_ZN1c4dumpEv>	/* c1调用dump */
	c2.dump();
   104d6:	463b      	mov	r3, r7				/* r3 = sp */
   104d8:	4618      	mov	r0, r3				/* r0 = r3 */
   104da:	f000 f82b 	bl	10534 <_ZN1c4dumpEv>	/* c2调用dump */

	return 0;
   104de:	2300      	movs	r3, #0			/* r3 = 0 */
}
   104e0:	4618      	mov	r0, r3				/* r0 = 0 */
   104e2:	3710      	adds	r7, #16			/* r7 += 16 */
   104e4:	46bd      	mov	sp, r7				/* sp = r7 */
   104e6:	bd80      	pop	{r7, pc}

000104e8 <_ZN1cC1Ev>:
	c() {
   104e8:	b480      	push	{r7}
   104ea:	b083      	sub	sp, #12
   104ec:	af00      	add	r7, sp, #0
   104ee:	6078      	str	r0, [r7, #4]	/* 构造函数返回的this指针 */
		v1 = 667;
   104f0:	687b      	ldr	r3, [r7, #4]	/* r3 = r7+4 = this */
   104f2:	f240 229b 	movw	r2, #667	; 0x29b
   104f6:	601a      	str	r2, [r3, #0]	/* r3+0 = this.v1 = 667 */
		v2 = 999;
   104f8:	687b      	ldr	r3, [r7, #4]	/* r3 = r7+4 = this */
   104fa:	f240 32e7 	movw	r2, #999	; 0x3e7
   104fe:	605a      	str	r2, [r3, #4]	/* r3+4 = this.v2 = 999 */
	}
   10500:	687b      	ldr	r3, [r7, #4]	/* r3 = r7+4 = this */
   10502:	4618      	mov	r0, r3			/* 返回值 */
   10504:	370c      	adds	r7, #12
   10506:	46bd      	mov	sp, r7
   10508:	f85d 7b04 	ldr.w	r7, [sp], #4
   1050c:	4770      	bx	lr

0001050e <_ZN1cC1Eii>:
	c(int a, int b)
   1050e:	b480      	push	{r7}
   10510:	b085      	sub	sp, #20
   10512:	af00      	add	r7, sp, #0
   10514:	60f8      	str	r0, [r7, #12]	/* 构造函数返回的this指针 */
   10516:	60b9      	str	r1, [r7, #8]	/* 参数 1 */
   10518:	607a      	str	r2, [r7, #4]	/* 参数 2 */
		v1 = a;
   1051a:	68fb      	ldr	r3, [r7, #12]
   1051c:	68ba      	ldr	r2, [r7, #8]	/* a */
   1051e:	601a      	str	r2, [r3, #0]	/* r3+0 = v1 = a */
		v2 = b;
   10520:	68fb      	ldr	r3, [r7, #12]
   10522:	687a      	ldr	r2, [r7, #4]	/* b */
   10524:	605a      	str	r2, [r3, #4]	/* r3+4 = v2 = b */
	}
   10526:	68fb      	ldr	r3, [r7, #12]
   10528:	4618      	mov	r0, r3			/* 返回值 */
   1052a:	3714      	adds	r7, #20
   1052c:	46bd      	mov	sp, r7
   1052e:	f85d 7b04 	ldr.w	r7, [sp], #4
   10532:	4770      	bx	lr

00010534 <_ZN1c4dumpEv>:
	void dump() {
   10534:	b580      	push	{r7, lr}
   10536:	b082      	sub	sp, #8
   10538:	af00      	add	r7, sp, #0
   1053a:	6078      	str	r0, [r7, #4]	/* this 指针 */
		printf("%d, %d\n", v1, v2);
   1053c:	687b      	ldr	r3, [r7, #4]	/* r3 = this */
   1053e:	6819      	ldr	r1, [r3, #0]	/* r1 = [r3+0] = v1 */
   10540:	687b      	ldr	r3, [r7, #4]	/* r3 = this */
   10542:	685b      	ldr	r3, [r3, #4]	/* r3 = [r3+4] = v2 */
   10544:	461a      	mov	r2, r3			/* r2 = r3 = v2 */
   10546:	f240 50a8 	movw	r0, #1448	; 0x5a8		/* r0 = 0x5a8 */
   1054a:	f2c0 0001 	movt	r0, #1					/* r0 = (1 << 16) | 0x05a8 = 0x105a8，此为数据段地址 */
   1054e:	f7ff ef38 	blx	103c0 <printf@plt>	/* printf(r0, r1, r2) */
	}
   10552:	bf00      	nop
   10554:	3708      	adds	r7, #8
   10556:	46bd      	mov	sp, r7
   10558:	bd80      	pop	{r7, pc}
	...

#endif
